#include "Hopfield.h"

// Constructor
Hopfield::Hopfield(){
	this->nbNeurones=LARGEUR*HAUTEUR;
	this->neurones = (int*)malloc(sizeof(int)*nbNeurones);
    this->synapses = (int**) malloc(nbNeurones*sizeof(int*));
    for (int i = 0; i < nbNeurones; i++){
        this->synapses[i] = (int*) malloc(nbNeurones*sizeof(int));
    }
    valeurEnergie=100.0;
    
}

/*void Hopfield::apprendre(){
    
}*/

void Hopfield::apprentissage(){
   
    for(int i = 0; i < this->nbNeurones; i++){
        for(int j = 0; j < this->nbNeurones; j++){
            if(i != j){
                this->synapses[i][j] += this->neurones[i] * this->neurones[j];
            }
        }
    }
    
}

void Hopfield::transformer(){
    
    float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
    int k = (int) (r * this->nbNeurones);
    
    this->neurones[k] *= -1;
    
    for(int i = 0; i < this->nbNeurones; i++){
        int somme = 0;
        for(int j = 0; j < this->nbNeurones; j++){
            somme += this->synapses[i][j] * this->neurones[j];
        }
        somme += this->neurones[i];
        if(somme >= 0){
            this->neurones[i] = 1;
        }else{
            this->neurones[i] = -1;
        }
    }
}

float Hopfield::energie(){
    
    float cumul = (float) 0.0;
    for(int i = 0; i < this->nbNeurones; i++){
        for(int j = 0; j < this->nbNeurones; j++){
			if(i!=j){
				cumul -= 0.5 * this->synapses[i][j] * this->neurones[i] * this->neurones[j];
			}
        }
    }
    return cumul;
    
}

/* APPREND AU RESEAU UN NOUVEAU CARACTERE 
*  Enregistre les valeurs (pixels) du caractere dans les differents neurones
*/
void Hopfield::setCaractere(int caractere[LARGEUR][HAUTEUR]){
	for(int i=0; i<LARGEUR; i++){
		for(int j=0; j<LARGEUR;j++){
			this->neurones[j+i*LARGEUR]=caractere[i][j];
		}
	}
}

void Hopfield::afficherCaractere(int caractere[LARGEUR][HAUTEUR]){
    int i,j;
	char empty[50] = " ";
	char filled[50] = "X";
    for(i=0; i<LARGEUR; i++){
        for(j=0; j<HAUTEUR; j++){
			if(caractere[i][j]==-1){
				printf("%s", empty);
			}else{
				printf("%s", filled);			
			}
        }
        printf("\n");
    }
    printf("====================\n");
}

void Hopfield::afficherCaractereCourant(){
	//vecteur de neurones to matrice caractere
	int caractere[LARGEUR][HAUTEUR] ;
	
	int largeurCount=0;
	int hauteurCount=0;
	for(int i=0; i<LARGEUR*HAUTEUR; i++){
		caractere[hauteurCount][largeurCount]=this->neurones[i];
		largeurCount++;
		if(largeurCount==LARGEUR){
			largeurCount=0;
			hauteurCount++;
		}
	}
	
	//affichage du caractere
	this->afficherCaractere(caractere);
}